//
//  memory.cpp
//  HelloWorld
//
//  Created by Kevin Tang on 30/12/14.
//  Copyright (c) 2014年 Kevin Tang. All rights reserved.
//

#include "memory.h"
#include <iostream>
#include <vector>
#include <boost/smart_ptr/scoped_ptr.hpp>
#include <boost/smart_ptr/scoped_array.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/make_shared.hpp>
using namespace std;
using namespace boost;


class posix_file
{
public:
    posix_file(const char * filename)
    {
        cout<<"open file"<< filename << endl;
    }

    ~posix_file()
    {
        cout << "close file " << endl;
    }
    
};

void test_scoped_ptr()
{
    //不能拷贝，赋值，== != 比较。不适合用于容器
    //指针的作用域，离开作用域范围即自动释放
    scoped_ptr<int> sp(new int);
    
    if(sp){
        *sp = 10;
        cout<< *sp <<endl;
    }
    
    sp.reset();
    assert(sp == 0);
    
    if(!sp){
        cout << "scope_ptr == null " <<endl;
    }
    
    scoped_ptr<posix_file> p(new posix_file("Hello.txt"));

}

void test_scoped_array()
{
    int *arry =  new  int[100];
    scoped_array<int> p(arry);//接管内存释放任务
    fill_n(&p[0], 100, 5);
    
    for (int i=0; i<100; i++) {
        cout<< p[i] << endl;
    }
}

//================ boost::shared_ptr 在桥接模式的使用=============
class Sample//这个声明，假设是放在头文件中的。
{
    private :
    class impl; //一个类的声明,具体的实现放在.cpp中
    boost::shared_ptr<impl> m_pimpl;
public:
    Sample();
    void print();//公开的方法
};

class Sample::impl//这个类是 Sample类的具体实现，外界是不知道其实现的
{
public:
    void  print()
    {
        cout<< "print called " <<endl;
    }
};

//注意 impl的完整声明，需要在这个构造函数之前。因为 new impl 需要知道这个类的构造方法。
//而前面的  boost::shared_ptr<impl> m_pimpl 由于是个指针，所以不需要类的完整声明。
//只需要用 class impl;这样一个不完整的专用明就可以了。
Sample::Sample():m_pimpl( new impl)
{
   //外部在调用Sample()构造时，根本不知道，我内部创建了一个 impl对象
   //由于这个内部对象，由boost::shared_ptr接管了对象的释放。所以不需要在Sample的释构中调用delete 释放。非常方便
}

void Sample::print()
{
    m_pimpl->print();
}
//================================================================

void print_func(boost::shared_ptr<int> p)
{
    cout<< "count:" << p.use_count() << "value=" <<*p<<endl;
}

void test_shared_ptr()
{
    class shared
    {
        private:
            boost::shared_ptr<int> p;
        public:
            shared(boost::shared_ptr<int> p_):p(p_){}
            void print()
            {
                cout<< "count:" << p.use_count() << "value=" <<*p<<endl;
            }
    };
    
    cout << "======== test shared_ptr reference count START========" <<endl;
    boost::shared_ptr<int> p(new int(100));//创建一个整型变量，值为100
    shared s1(p),s2(p);
    
    s1.print();
    s2.print();
    
    *p = 20;
    print_func(p);
    s1.print();
    cout << "======== test shared_ptr reference count END========" <<endl;
    
    cout << "======== boost::make_shared START========" <<endl;
    //下面是工作赋值模板的应用
    boost::shared_ptr<string> pstr = boost::make_shared<string>("Hello world");//相当于 new string("Hello world");
    
    cout<< pstr->c_str() <<endl;
    string *temp = new string("how are you ");
    cout<< temp->c_str()<<endl;
    delete temp;
    cout << "======== boost::make_shared END========" <<endl;
    
    
    cout << "======== boost::shared_ptr< vector<int> > spv START========" <<endl;
    //spv 是一个指向 vector<int> 的指针
    boost::shared_ptr< vector<int> > spv =  boost::make_shared< vector<int>>(10,2);//10个元素，每个元素是2
    vector<int > value(10,2);
    cout<< value.size() <<endl;
    for(int i=0;i<value.size();i++){
        cout<< value[i]<< spv->at(i) <<", ";
    }
    cout<<endl;
    
    
    //与上面spv 的第一句等同,但是由于我们使用了new 在堆上分配了内存，我们要用delete释放,
    //而上面的 spv则会自动调用delete释放make_shared 分配的内存
    vector<int > *pp = new vector<int>(10,2);
    for (int j=0; j < pp->size(); j++) {
        cout<<pp->at(j)<<", ";
    }
    delete pp;
    cout<<endl;
    cout << "======== boost::shared_ptr< vector<int> > spv END========" <<endl;
    
    //========另一种应用，将boost::shared_ptr指针，做为容器的元素============
    {
        cout << "======== vector< boost::shared_ptr< int> > START========" <<endl;
        typedef vector< boost::shared_ptr< int> > VS;
        
        VS vs(10);//声明一个vector ,持有10个元素，每个元素是一个指针，并置为0;
                 //并且，如果后面给每个指针分配了内存，它们会自动释放，不需要手delete;
        
        int i=1;
        for (VS::iterator p = vs.begin(); p != vs.end(); p++) {
            (*p) = boost::make_shared<int>(i++);// new int(i++)
            cout << (*(*p))<<" ,";
            }
        cout<<endl;
        
        //下面的 vp 存储10个指向 int类型的指针，由于没有使用 boost::shared_ptr 所以，我们要手动delete
        vector<int *> vp(10);
        int j = 1;
        for (vector<int *>::iterator p = vp.begin(); p != vp.end(); p++) {
            (*p) = new int(j++);
            cout << (*(*p))<<" ,";
        }
        //我们需要释放这10个 int 指针
        for (vector<int *>::iterator p = vp.begin(); p != vp.end(); p++) {
            delete (*p);
            *p = NULL;//必须赋值为 NULL,否则下面的判断不成立。因为是野指针
        }
        cout<< endl;
        
        if(vp[0] == NULL)
        {
            cout<<" vp[0].... is release"<<endl;
        }
        
        cout << "======== vector< boost::shared_ptr< int> > END========" <<endl;
    }
  
    
    cout << "======== boost::shared_ptr use in bridge mode START========" <<endl;
    {//具体要看 Sample类的声明与定义
        Sample s;
        s.print();
    }
    
    cout << "======== boost::shared_ptr use in bridge mode END========" <<endl;
}







void test_memory()
{
   // test_scoped_ptr();

   // test_scoped_array();
    test_shared_ptr();
}

